package org.duang.db.mongo.parser.decode;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.duang.db.annotation.VoColl;
import org.duang.db.mongo.parser.DecodeConvetor;
import org.duang.kit.DataType;
import org.duang.kit.ObjectKit;
import org.duang.kit.ToolsKit;

import com.mongodb.DBObject;
/**
 * 对象集合解码
 * @author laotang
 *
 */
public class VoCollDecoder extends Decoder {

	public VoCollDecoder(DBObject dbo, Field field) {
		super(dbo, field);	
		//如果有注入别名，则按别名取值
		String name = getFieldName();
		if(ToolsKit.isNotEmpty(name)){
			value = dbo.get(name);
		}
	}

	@SuppressWarnings("rawtypes")
	@Override
	public void setObj(Object obj) {
		Class<?> type = field.getType();
		if(type.isArray()){
			decodeByArray(obj, type.getComponentType());
		}else{
			ParameterizedType paramType = (ParameterizedType)field.getGenericType();
			Type[] types = paramType.getActualTypeArguments();
			if(types.length == 1){
				decodeByCollection(obj, (Class)types[0]);
			}else if(types.length == 2){
				decodeByMap(obj, (Class)types[1]);
			}
		}
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private void decodeByArray(Object obj, Class cls){
		List list = (ArrayList)value;
		if(ToolsKit.isEmpty(list)) return;
		int size = list.size();
		Object arr = Array.newInstance(cls, size);
		for (int i = 0; i < size; i++) {
			Object objItem = list.get(i);
			if(ToolsKit.isNotEmpty(objItem)){
				DBObject dbo = (DBObject)objItem;
				Array.set(arr, i, DecodeConvetor.convetor(cls, dbo));
			}else{
				Array.set(arr, i, null);
			}
		}
		ObjectKit.setField(obj, field, arr);
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private void decodeByCollection(Object obj, Class cls){		
		List list = (ArrayList)value;
		if(null == list) return;
		List result = new ArrayList();
		for (Object object : list) {
			if(ToolsKit.isNotEmpty(object)){
				Object voObj = DecodeConvetor.convetor(cls, (DBObject)object);
				result.add(voObj);
			}
		}
		Class type = field.getType();
		if(DataType.isListType(type)){
			ObjectKit.setField(obj, field, result);
		}else if(DataType.isSetType(type)){
			ObjectKit.setField(obj, field, new HashSet(result));
		}else if(DataType.isQueueType(type)){
			ObjectKit.setField(obj, field, new LinkedList(result));
		}
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private void decodeByMap(Object obj, Class cls){
		Map map = (Map)value;
		if(null == map) return;
		Map result = new HashMap();
		Iterator<Entry<String, Object>> it = map.entrySet().iterator();
		while(it.hasNext()){
			Entry<String, Object> entry = it.next();
			if(ToolsKit.isNotEmpty(entry)){
				Object voObj = DecodeConvetor.convetor(cls, (DBObject)entry.getValue());
				result.put(entry.getKey(), voObj);
			}else{
				result.put(entry.getKey(), null);
			}
		}
		ObjectKit.setField(obj, field, result);
	}
	

	@Override
	public String getFieldName() {
		String fieldName = field.getAnnotation(VoColl.class).name();
		return (ToolsKit.isNotEmpty(fieldName)) ? fieldName : field.getName();
	}

	@Override
	public Object getFieldValue() {
		return value;
	}

	@Override
	public boolean isNullField() {
		return null == value;
	}
}
